package com.gitee.fsmxm.thinking.in.concurrent.basic;

/**
 * 死锁问题
 * 发生条件：
 * 1. 互斥，共享资源 X 和 Y 只能被一个线程占用；
 * 2. 占有且等待，线程 T1 已经取得共享资源 X，在等待共享资源 Y 的时候，不释放共享资源 X；
 * 3. 不可抢占，其他线程不能强行抢占线程 T1 占有的资源；
 * 4. 循环等待，线程 T1 等待线程 T2 占有的资源，线程 T2 等待线程 T1 占有的资源，就是循环等待。
 */
public class _03_DeadLock {
    /**
     * 账户类
     */
    static class Account {
        int balance; // 账户余额
        int id; // 账户id

        public Account(int balance, int id) {
            this.balance = balance;
            this.id = id;
        }

        void transfer(final Account target, int amount) {
            synchronized (this) { // 锁转出账户
                if (balance > amount) {
                    synchronized (target) { // 锁转入账户 (可能出现死锁）
                        balance -= amount;
                        target.balance += amount;
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final Account a1 = new Account(100, 1000);
        final Account a2 = new Account(300, 2000);

        // a1 给 a2 转 20块
        Thread t1 = new Thread(() -> a1.transfer(a2, 20));
        // a2 给 a1 转 50块
        Thread t2 = new Thread(() -> a2.transfer(a1, 50));

        // 两个人转账同时发生 （也可以断点模拟调试）
        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println(a1.balance);
        System.out.println(a2.balance);
    }
}
